package com.pig4cloud.pigx.wallet.websocket.manager;

import com.pig4cloud.pigx.wallet.vo.AbstractTopicVO;
import com.pig4cloud.pigx.wallet.websocket.message.SubscribeMessage;
import com.pig4cloud.pigx.wallet.websocket.message.UnSubscribeMessage;
import com.pig4cloud.pigx.wallet.websocket.subscribe.*;
import jodd.util.collection.MapEntry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class WsManager {

	@Autowired
	private ContractAccountHandler contractAccount;

	@Autowired
	private CapitalAccountHandler capitalAccount;

	@Autowired
	private TotalAssetsHandler totalAssetsHandler;

	@Autowired
	private WalletNoticeHandler walletNoticeHandler;

	@Autowired
	private MergeWallet mergeWallet;

 	public Map<WebSocketSession,Long>  webSocketSessionMap = new ConcurrentHashMap<WebSocketSession,Long>();
	private WsManager() {
		init();
	}

	public void init(){
		check();
	}
	public void subscribe(WebSocketSession session, SubscribeMessage subscribeMessage){
		if(webSocketSessionMap.get(session) == null){
			webSocketSessionMap.put(session,System.currentTimeMillis());
		}
		String topicName= subscribeMessage.getParams().get(0);
		switch (topicName) {
			case "contractAccount":
				contractAccount.sub(session,subscribeMessage.getParams());
				break;
			case "capitalAccount":
				capitalAccount.sub(session,subscribeMessage.getParams());
				break;
			case "totalAssets":
				totalAssetsHandler.sub(session,subscribeMessage.getParams());
				break;
			case "walletNotice":
				walletNoticeHandler.sub(session,subscribeMessage.getParams());
				break;
			case "mergeWallet":
				AbstractTopicVO sub = mergeWallet.sub(session, subscribeMessage.getParams());
				Map.Entry<WebSocketSession, AbstractTopicVO> mergeEntry = new MapEntry<>(session,sub);
				mergeWallet.sendMessage(mergeEntry);
				break;
			default: break;
		}

	}
	public void unsubscribe(WebSocketSession session, UnSubscribeMessage unsubscribeMessage){
		contractAccount.unsub(session,unsubscribeMessage.getParams());
		capitalAccount.unsub(session,unsubscribeMessage.getParams());
		totalAssetsHandler.unsub(session,unsubscribeMessage.getParams());
		walletNoticeHandler.unsub(session,unsubscribeMessage.getParams());
		mergeWallet.unsub(session,unsubscribeMessage.getParams());
	}

	private void check(){
		ScheduledExecutorService service= Executors.newSingleThreadScheduledExecutor();
		service.scheduleAtFixedRate(() -> {
			try {
				webSocketSessionMap.forEach((k,v)->{
					if(!k.isOpen()){
						webSocketSessionMap.remove(k);
						if(contractAccount.subList.containsKey(k)){
							contractAccount.subList.remove(k);
						}
						if(capitalAccount.subList.containsKey(k)){
							capitalAccount.subList.remove(k);
						}
						if(totalAssetsHandler.subList.containsKey(k)){
							totalAssetsHandler.subList.remove(k);
						}
						if(walletNoticeHandler.subList.containsKey(k)){
							walletNoticeHandler.subList.remove(k);
						}
						if(mergeWallet.subList.containsKey(k)){
							mergeWallet.subList.remove(k);
						}
					}
				});
			} catch (Exception ignored) {

			}
		},10,10, TimeUnit.SECONDS);

	}

}
